#include "ipc/mutex.h"
#include "core/task.h"
#include "cpu/irq.h"

void mutex_init (mutex_t * mutex){
    mutex->owner=(task_t *)0;
    mutex->owner=0;
    list_init(&mutex->wait_list);
};

void mutex_lock (mutex_t * mutex){
    irq_state_t state = irq_enter_protection();
    task_t *current_task=get_task_current();

    if(mutex->locked_count==0){
        // 之前没有上锁，让他获取锁
        mutex->owner=current_task;
        mutex->locked_count++;
    }else if(mutex->owner==current_task){
        // 这之前就是我的锁
        mutex->locked_count++;
    }
    else{
        // 已经上锁，加入到等待队列中
        task_set_block(current_task);
        list_insert_last(&mutex->wait_list,&current_task->wait_node);
        task_dispatch();
    }

    irq_leave_protection(state);
};

void mutex_unlock (mutex_t * mutex){
    irq_state_t state = irq_enter_protection();

    task_t *current_task=get_task_current();
    if(mutex->owner==current_task){
        // 是这个进程的锁
        if(--mutex->locked_count==0){
            // 释放锁
            mutex->owner=(task_t *)0;

            // 唤醒等待队列里的进程
            if(list_count(&mutex->wait_list)){
                list_node_t *wait_task_node=list_remove_first(&mutex->wait_list);
                task_t *wait_task=list_node_parent(wait_task_node,task_t,wait_node);
                task_set_ready(wait_task);

                mutex->owner=wait_task;
                mutex->locked_count=1;

                task_dispatch();
            }
        }
    }

    irq_leave_protection(state);
};